#!/bin/bash
exec >trafficgen-infra-stderrout.txt
exec 2>&1

. /usr/bin/trafficgen-base || (echo "/usr/bin/trafficgen-base not found"; exit 1)

dump_runtime
validate_label
validate_sw_prereqs
validate_other_prereqs

# defaults
trex_bin="_t-rex-64-o"
tgen_dir=/opt/trafficgen
sample_dir="`/bin/pwd`"
trex_cfg="$sample_dir/trex_cfg.yaml"
max_loss_pct=0.002
rate=100
rate_unit="%"
one_shot="0"
# TODO: Auto adjust limit based on actual requirement (which is probably number of interfaces)
mem_limit=2048
longopts="active-devices:,devices:,cpus:,mem-limit:"
opts=$(getopt -q -o "" --longoptions "$longopts" -- "$@");
eval set -- "$opts";
while true; do
    case "$1" in
        --active-devices)
            shift
            active_devices=$1
            shift
            ;;
        --mem-limit)
            shift
            mem_limit=$1
            shift
            ;;
        --devices)
            shift
            devices=$1
            shift
            ;;
        --cpus)
            shift
            cpus=$1
            shift
            ;;
        --)
            shift
            break
            ;;
        *)
            echo "Ignoring option: $1"
            shift
            shift
            ;;
    esac
done

if [ -z "$active_devices" ]; then
    active_devices="$devices"
fi

if [ -z "$(command -v binary-search.py)" ]; then
    exit_error "binary-search.py is missing" 1 "$sample_dir"
fi
if [ ! -e /usr/bin/python3 ]; then
    exit_error "cannot find /usr/bin/python3, exiting" 1 "$sample_dir"
fi

echo "Checking for TRex service"
if pgrep $trex_bin; then
    echo "TRex launched from previous test" | tee $sample_dir/trex-server-running.txt
else
    echo "Starting TRex service"
    if [ -z "$cpus" ]; then
        # User did not specify CPUs, so use what's available
        # If this is run on a bare-metal host set up with
        # cpu-partitioning, this is not going to work.  The
        # user needs to specify what CPUs to use for TRex.
        cpus=${WORKLOAD_CPUS}
        if [ -z "$cpus" ]; then
            exit_error "CPUs for TRex have not been defined.  Either --cpus was not used, or WORKLOAD_CPUS was not defined (cpu-partitioning endpoint-option was not used)" 1 "$sample_dir"
        fi
    fi
    cpus_expanded="`expand_number_list $cpus`"
    cpus_separated="`separate_comma_list $cpus_expanded`"
    echo
    echo "TRex cpus: $cpus_separated"

    trex_dir=/opt/trex/current

    pushd $trex_dir
    interface_state_cmd="./dpdk_setup_ports.py -t"
    echo "interface status: $interface_state_cmd"
    ${interface_state_cmd}
    echo; echo
    echo "Resolving devices for trex based on devices [$devices]"
    trex_dev_opt=""
    for dev in `echo $devices | sed -e 's/,/ /g'`; do
        res_dev=""
        resolve_device res_dev $dev
        trex_dev_opt+=" $res_dev"
    done
    if [ -z "$trex_dev_opt" ]; then
        exit_error "TRex devices could not be found" 1 "$sample_dir"
    fi
    # Infra script does not need to use "active" devices, but
    # we might as well validate it now.
    echo "Resolving *active* devices for trex based on [$active_devices]"
    trex_active_dev_opt=""
    position=1
    for dev in `echo $active_devices | sed -e 's/,/ /g'`; do
        res_dev=""
        resolve_device res_dev $dev $position
        trex_active_dev_opt+=" $res_dev"
    done
    if [ -z "$trex_active_dev_opt" ]; then
        exit_error "TRex active devices could not be found" 1 "$sample_dir"
    fi

    echo
    trex_dumppci_cmd="./dpdk_setup_ports.py --dump-pci-description"
    echo "getting pci configuration with: $trex_dumppci_cmd"
    $trex_dumppci_cmd
    echo; echo
    if [ -z "$(command -v gen-trex-cfg.py)" ]; then
        exit_error "gen-trex-cfg.py is missing" 1 "$sample_dir"
    fi
    trex_config_cmd="gen-trex-cfg.py --output-file ${trex_cfg} --memory-limit ${mem_limit}"
    for trex_dev in ${trex_dev_opt}; do
        trex_config_cmd+=" --device ${trex_dev}"
    done
    for trex_cpu in ${cpus_separated}; do
        trex_config_cmd+=" --cpu ${trex_cpu}"
    done
    echo "configuring trex with: ${trex_config_cmd}"
    ${trex_config_cmd}
    if [ ! -e ${trex_cfg} ]; then
	exit_error "${trex_cfg} not found, gen-trex-cfg.py probably failed" 1 "$sample_dir"
    fi
    echo "ls -l $trex_cfg"
    /bin/ls -l $trex_cfg
    echo
    echo "trex config file:"
    cat $trex_cfg
    echo

    trex_server_cmd="./$trex_bin -i --checksum-offload --cfg $trex_cfg --iom 0 -v 4 --prefix trafficgen_trex_ --mlx5-so --close-at-end"
    echo "about to run: $trex_server_cmd"
    $trex_server_cmd >$sample_dir/trex-server-stderrout.txt 2>&1 &
    echo $! >$sample_dir/trex-server-pid.txt
    popd
fi

count=0
secs=0
trex_ready=0
interval=5
while [ $trex_ready -eq 0 -a $count -lt 10 ]; do
    sleep $interval
    echo "checking for TRex server"
    ss -tlnp
    ss -tlnp | grep -q ":4500" && trex_ready=1
    let count=$count+1
    let sec=$sec+$interval
done
if [ $trex_ready -eq 1 ]; then
    echo "Trex server up after $sec seconds"
else
     exit_error "Trex server failed to start" 1 "$sample_dir"
fi

sleep 20 # Waiting for device to init
trex_query_bin=$(command -v trex-query.py)
if [ -z "${trex_query_bin}" ]; then
    exit_error "trex-query.py is missing" 1 "$sample_dir"
fi
echo
echo "Active Device MAC info:"
mac_list=""
for active_dev in $(echo ${active_devices} | sed -e 's/,/ /g'); do
    dev_idx=0
    for dev in $(echo ${devices} | sed -e 's/,/ /g'); do
        if [ "${active_dev}" == "${dev}" ]; then
            echo "found ${active_dev} in device list at index ${dev_idx}"
            dev_mac=$(/usr/bin/python3 ${trex_query_bin} --device ${dev_idx} 2>&1 | grep "PARSABLE PORT INFO" | sed -e 's/PARSABLE PORT INFO: //' | jq -r '.[0].hw_mac')
            echo "${active_dev} has MAC=${dev_mac}"
            mac_list+="\"${dev_mac}\","
        fi

        (( dev_idx++ ))
    done
done
mac_list=$(echo "${mac_list}" | sed -e 's/,$//')
echo "TRex source MACs: ${mac_list}"

# MAC info, to be sent to endpoint and then forwarded to the server 
echo '{"recipient":{"type":"all","id":"all"},"user-object":{"macs":['${mac_list}']}}' >msgs/tx/macs
